home *** CD-ROM | disk | FTP | other *** search
/ CD World Haziran 1997 / CD World Haziran 1997.iso / Cesitlemeler / Directx 3.0 / dx3.exe / SDK / SAMPLES / DUEL / WIZARD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  30.6 KB  |  957 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:       wizard.c
  6.  *  Content:    User input (setup wizard) related code
  7.  *
  8.  *
  9.  ***************************************************************************/
  10. #include <windows.h>
  11. #include "prsht.h"
  12. #include "wizard.h"
  13. #include "util.h"
  14. #include "comm.h"
  15. #include "gameproc.h"
  16.  
  17. /*
  18.  * Externals
  19.  */
  20. extern HINSTANCE                ghinst;             // program instance
  21. extern HWND                     ghWndMain;          // main window
  22. extern BOOL                     gbIsHost;           // is the user hosting/joining a game
  23. extern DPID                     gOurID;             // player id
  24. extern LPGUID                   glpGuid;            // duel's guid
  25.  
  26. /*
  27.  * Globals to this module
  28.  */
  29. static HFONT                    ghTitleFont;        // font for titles on setup wizard
  30. static HFONT                    ghHeadingFont;      // font for headings on setup wizard
  31. static int                      gnSession,gnPlayer; // indexes for tree view images
  32. static HKEY                     ghDuelKey=NULL;     // duel registry key handle
  33. static DWORD                    gdwDuelDisp;        // key created or opened
  34. static GUID                     gSPGuid;            // currently selected service provider guid
  35. static HTREEITEM                ghtiSession;        // points to a visible session item in tree control
  36.                                                     //  used for inserting players into tree control
  37. static HWND                     ghWndSPCtl;         // handle to service provider control
  38.  
  39. /*
  40.  * SetupFonts
  41.  *
  42.  * Initializes font structures (used for wizard controls)
  43.  */
  44. void SetupFonts(HDC hDC)
  45. {
  46.     LOGFONT lf;
  47.     TCHAR tszFontName[MAX_FONTNAME];
  48.  
  49.     LoadString(ghinst, IDS_WIZARD_FONTNAME, tszFontName, MAX_FONTNAME);
  50.  
  51.     ZeroMemory(&lf,sizeof(lf));
  52.     lf.lfHeight = -MulDiv(11,GetDeviceCaps(hDC, LOGPIXELSY),72);
  53.     lf.lfWeight = 500;
  54.     lf.lfItalic = TRUE;
  55.     _tcscpy(lf.lfFaceName,tszFontName);
  56.     ghTitleFont = CreateFontIndirect(&lf);
  57.  
  58.     ZeroMemory(&lf,sizeof(lf));
  59.     lf.lfHeight = -MulDiv(11,GetDeviceCaps(hDC, LOGPIXELSY),72);
  60.     lf.lfWeight = 500;
  61.     _tcscpy(lf.lfFaceName,tszFontName);
  62.     ghHeadingFont = CreateFontIndirect(&lf);
  63. }
  64.  
  65. /*
  66.  * CleanupFonts
  67.  *
  68.  * Cleans up font structures
  69.  */
  70. void CleanupFonts(void)
  71. {
  72.     if (ghTitleFont) DeleteObject(ghTitleFont);
  73.     if (ghHeadingFont) DeleteObject(ghHeadingFont);
  74. }
  75.  
  76. /*
  77.  * RegSet
  78.  *
  79.  * Stores a data value in the registry
  80.  */
  81. LONG RegSet(LPCTSTR lptszName, CONST BYTE * lpData, DWORD dwSize)
  82. {
  83. #ifdef UNICODE
  84.     dwSize *= 2; // calc number of bytes
  85. #endif
  86.     return RegSetValueEx(ghDuelKey, lptszName, 0, REG_SZ, lpData, dwSize);
  87. }
  88.  
  89. /*
  90.  * RegSetA
  91.  *
  92.  * Stores data as an ascii string in the registry
  93.  */
  94. LONG RegSetA(LPCTSTR lptszName, CONST BYTE * lpData, DWORD dwSize)
  95. {
  96.     return RegSetValueEx(ghDuelKey, lptszName, 0, REG_SZ, lpData, dwSize);
  97. }
  98.  
  99. /*
  100.  * RegGet
  101.  *
  102.  * Queries a value from the registry
  103.  */
  104. LONG RegGet(LPCTSTR lptszName, LPBYTE lpData, LPDWORD lpdwDataSize)
  105. {
  106.     DWORD dwType;
  107.  
  108.     return RegQueryValueEx(ghDuelKey, lptszName, NULL, &dwType, lpData, lpdwDataSize);
  109. }
  110.  
  111. /*
  112.  * DoWizard
  113.  *
  114.  * Creates and launches a wizard (property sheets) for user input
  115.  */
  116. DWORD WINAPI DoWizard(LPVOID pv)
  117. {
  118.     PROPSHEETPAGE psp[4];
  119.     PROPSHEETHEADER psh;
  120.     TCHAR tszTitle1[MAX_WINDOWTITLE];
  121.     TCHAR tszTitle2[MAX_WINDOWTITLE];
  122.     TCHAR tszTitle3[MAX_WINDOWTITLE];
  123.     TCHAR tszTitle4[MAX_WINDOWTITLE];
  124.     TCHAR tszTitle5[MAX_WINDOWTITLE];
  125.  
  126.     LoadString(ghinst, IDS_WIZARD_TITLE_SP, tszTitle1, MAX_WINDOWTITLE); 
  127.     LoadString(ghinst, IDS_WIZARD_TITLE_GS, tszTitle2, MAX_WINDOWTITLE); 
  128.     LoadString(ghinst, IDS_WIZARD_TITLE_JS, tszTitle3, MAX_WINDOWTITLE); 
  129.     LoadString(ghinst, IDS_WIZARD_TITLE_HS, tszTitle4, MAX_WINDOWTITLE); 
  130.     LoadString(ghinst, IDS_WIZARD_TITLE, tszTitle5, MAX_WINDOWTITLE); 
  131.  
  132.     psp[0].dwSize = sizeof(PROPSHEETPAGE);
  133.     psp[0].dwFlags = PSP_USEICONID | PSP_USETITLE;
  134.     psp[0].hInstance = ghinst;
  135.     psp[0].pszTemplate = MAKEINTRESOURCE(IDD_CHOOSEPROVIDER);
  136.     psp[0].pszIcon = NULL; 
  137.     psp[0].pfnDlgProc = DlgProcChooseProvider;
  138.     psp[0].pszTitle = tszTitle1;
  139.     psp[0].lParam = 0;
  140.     psp[0].pfnCallback = NULL;
  141.  
  142.     psp[1].dwSize = sizeof(PROPSHEETPAGE);
  143.     psp[1].dwFlags = PSP_USEICONID | PSP_USETITLE;
  144.     psp[1].hInstance = ghinst;
  145.     psp[1].pszTemplate = MAKEINTRESOURCE(IDD_GAMESETUP);
  146.     psp[1].pszIcon = NULL; 
  147.     psp[1].pfnDlgProc = DlgProcGameSetup;
  148.     psp[1].pszTitle = tszTitle2;
  149.     psp[1].lParam = 0;
  150.     psp[1].pfnCallback = NULL;
  151.  
  152.     psp[2].dwSize = sizeof(PROPSHEETPAGE);
  153.     psp[2].dwFlags = PSP_USEICONID | PSP_USETITLE;
  154.     psp[2].hInstance = ghinst;
  155.     psp[2].pszTemplate = MAKEINTRESOURCE(IDD_JOINSESSION);
  156.     psp[2].pszIcon = NULL; 
  157.     psp[2].pfnDlgProc = DlgProcJoinSession;
  158.     psp[2].pszTitle = tszTitle3;
  159.     psp[2].lParam = 0;
  160.     psp[2].pfnCallback = NULL;
  161.  
  162.     psp[3].dwSize = sizeof(PROPSHEETPAGE);
  163.     psp[3].dwFlags = PSP_USEICONID | PSP_USETITLE;
  164.     psp[3].hInstance = ghinst;
  165.     psp[3].pszTemplate = MAKEINTRESOURCE(IDD_HOSTSESSION);
  166.     psp[3].pszIcon = NULL; 
  167.     psp[3].pfnDlgProc = DlgProcHostSession;
  168.     psp[3].pszTitle = tszTitle4;
  169.     psp[3].lParam = 0;
  170.     psp[3].pfnCallback = NULL;
  171.     
  172.     psh.dwSize = sizeof(PROPSHEETHEADER);
  173.     psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE | PSH_WIZARD;
  174.     psh.hwndParent = ghWndMain;
  175.     psh.hInstance = ghinst;
  176.     psh.pszIcon = NULL;
  177.     psh.pszCaption = tszTitle5;
  178.     psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
  179.     psh.nStartPage = 0;
  180.     psh.ppsp = (LPCPROPSHEETPAGE) &psp;
  181.     psh.pfnCallback = NULL;
  182.  
  183.     // open/create duel registry key 
  184.     RegCreateKeyEx(HKEY_CURRENT_USER,
  185.                     DUEL_KEY,
  186.                     0,
  187.                     NULL,                   
  188.                     REG_OPTION_NON_VOLATILE,
  189.                     KEY_ALL_ACCESS,
  190.                     NULL,
  191.                     &ghDuelKey,
  192.                     &gdwDuelDisp
  193.                     );
  194.  
  195.     // setup fonts
  196.     SetupFonts(GetDC(ghWndMain));
  197.  
  198.     // launch the wizard
  199.     PropertySheet(&psh);
  200.  
  201.     // cleanup
  202.     CleanupFonts();
  203.  
  204.     // was communication initialized correctly ?
  205.     if (IsDPlay())
  206.     {
  207.         // if so, launch game
  208.         PostMessage( ghWndMain, UM_LAUNCH, 0, 0 );
  209.     }
  210.     else 
  211.     {
  212.         // otherwise, abort game
  213.         PostMessage( ghWndMain, UM_ABORT, 0, 0 );
  214.     }
  215.  
  216.     return 0;
  217. }
  218.  
  219. /*
  220.  * EnumSP
  221.  *
  222.  * DirectPlayEnumerate callback. Stores the service provider information in the 
  223.  * passed in list box control.
  224.  */
  225. BOOL WINAPI EnumSP(LPGUID lpGuid, LPTSTR lptszDesc, DWORD dwMajorVersion,
  226.                    DWORD dwMinorVersion, LPVOID lpv)
  227. {
  228.     LONG iIndex;
  229.     HWND hWnd = (HWND) lpv;
  230.     LPGUID lpSPGuid;
  231.  
  232.     // insert service provider description in the list box item
  233.     iIndex = SendMessage(hWnd, LB_ADDSTRING, 0, (LPARAM) lptszDesc);
  234.  
  235.     // allocate memory to remember the service provider guid
  236.     lpSPGuid = (LPGUID) malloc(sizeof(GUID));
  237.     if (!lpSPGuid) return FALSE;
  238.  
  239.     // copy guid
  240.     *lpSPGuid = *lpGuid;
  241.  
  242.     // store the service provider guid pointer as item data
  243.     if (iIndex != LB_ERR)
  244.         SendMessage(hWnd, LB_SETITEMDATA, iIndex, (LPARAM) lpSPGuid);
  245.  
  246.     return(TRUE);
  247. }
  248.  
  249. /*
  250.  * DlgProcChooseProvider
  251.  *
  252.  * Dialog procedure for the choose service provider dialog
  253.  */
  254. BOOL CALLBACK DlgProcChooseProvider(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  255. {
  256.     LPGUID  lpGuid;
  257.     static  LONG    iIndex;
  258.     static  HWND hWndCtl;
  259.     DWORD   dwSize;
  260.     BYTE    szSPGuid[GUIDSTR_MAX+1];
  261.     WCHAR   wszSPGuid[GUIDSTR_MAX+1];
  262.     int     i;
  263.     HRESULT hr;
  264.  
  265.     switch (msg)
  266.     {
  267.     case WM_NOTIFY:
  268.         switch (((NMHDR FAR *) lParam)->code) 
  269.         {
  270.         case PSN_SETACTIVE:
  271.             PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
  272.             return(TRUE);
  273.  
  274.         case PSN_WIZNEXT: 
  275.             // Release previously selected DPlay object, if any.
  276.             DPlayRelease();
  277.             if (iIndex != LB_ERR)
  278.             {
  279.                 lpGuid = (LPGUID) SendMessage(hWndCtl, LB_GETITEMDATA, iIndex, 0);
  280.                 
  281.                 if (lpGuid)
  282.                 {
  283.                     // remember the selection
  284.                     gSPGuid = *lpGuid;
  285.         
  286.                     // create directplay object
  287.                     if ((hr = DPlayCreate(lpGuid)) == DP_OK)
  288.                     {
  289.                         return(TRUE);
  290.                     }
  291.                     else
  292.                     {
  293.                         ShowError(IDS_DPLAY_ERROR_IDC);
  294.                     }
  295.                 }
  296.             }
  297.             SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  298.             return(TRUE);
  299.  
  300.         case PSN_QUERYCANCEL:
  301.             ReleaseSPData();
  302.             DPlayRelease();
  303.             return(TRUE);
  304.         }
  305.         break;
  306.  
  307.     case WM_INITDIALOG:
  308.         SendDlgItemMessage(hDlg, IDC_SP_TITLE, WM_SETFONT, (WPARAM)ghTitleFont, MAKELPARAM(TRUE,0));
  309.  
  310.         hWndCtl = GetDlgItem(hDlg, IDC_SERVICEPROVIDERS);
  311.         if (hWndCtl == NULL) return(TRUE);
  312.  
  313.         // remember the service provider control. used later in freeing sp information.
  314.         ghWndSPCtl = hWndCtl;
  315.         DirectPlayEnumerate(EnumSP, (LPVOID)hWndCtl);
  316.         SetFocus(hWndCtl);
  317.  
  318.         // setup user's saved preferences
  319.         iIndex = 0;
  320.         dwSize = GUIDSTR_MAX+1;
  321.         if (ghDuelKey && (RegGet(TEXT("ServiceProvider"), szSPGuid, &dwSize) == ERROR_SUCCESS)) 
  322.         {
  323.             AnsiToWide(wszSPGuid, szSPGuid, sizeof(szSPGuid));
  324.             GUIDFromString(wszSPGuid, &gSPGuid);
  325.  
  326.             for (i=0; i<SendMessage(hWndCtl, LB_GETCOUNT, 0, 0); i++)
  327.             {
  328.                 if (IsEqualGuid(&gSPGuid,(LPGUID)SendMessage(hWndCtl,LB_GETITEMDATA,i,0)))
  329.                 {
  330.                     iIndex = i;
  331.                     break;
  332.                 }
  333.             }
  334.         }
  335.  
  336.         SendMessage(hWndCtl, LB_SETCURSEL, iIndex, 0);
  337.         iIndex = SendMessage(hWndCtl, LB_GETCURSEL, 0, 0);
  338.         return(TRUE);
  339.  
  340.     case WM_COMMAND:
  341.         if ( HIWORD(wParam) == LBN_SELCHANGE)
  342.         {
  343.             iIndex = SendMessage(hWndCtl, LB_GETCURSEL, 0, 0);
  344.             
  345.             return(TRUE);
  346.         }
  347.         break;
  348.     }
  349.     return (FALSE);
  350. }
  351.  
  352. /*
  353.  * EnumSession
  354.  *
  355.  * EnumSessions callback. Inserts session description information in the passed in 
  356.  * tree view control.
  357.  */
  358. BOOL WINAPI EnumSession(LPCDPSESSIONDESC2 lpDPSessionDesc, LPDWORD lpdwTimeOut, DWORD dwFlags, 
  359.                         LPVOID lpContext)
  360. {
  361.     HWND hWnd = (HWND) lpContext;
  362.     HTREEITEM hItem;
  363.     LPGUID lpGuid;
  364.  
  365.     if(dwFlags & DPESC_TIMEDOUT) return FALSE;       // don't try again
  366.  
  367.     if (hWnd == NULL) return FALSE;
  368.  
  369.     // allocate memory to remember the guid
  370.     lpGuid = (LPGUID) malloc(sizeof(GUID));
  371.     if (!lpGuid) return FALSE;
  372.  
  373.     *lpGuid = lpDPSessionDesc->guidInstance;
  374. #ifdef UNICODE
  375.     hItem = AddItemToTree(hWnd, lpDPSessionDesc->lpszSessionName, (DWORD)lpGuid, 1);
  376. #else
  377.     hItem = AddItemToTree(hWnd, lpDPSessionDesc->lpszSessionNameA, (DWORD)lpGuid, 1);
  378. #endif
  379.     TreeView_SelectItem(hWnd, hItem);
  380.  
  381.     return(TRUE);
  382. }
  383.  
  384. /*
  385.  * DlgProcGameSetup
  386.  *
  387.  * Dialog procedure for the Game Setup Dialog.
  388.  */
  389. BOOL CALLBACK DlgProcGameSetup (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  390. {
  391.     switch (msg)
  392.     {
  393.     case WM_NOTIFY:
  394.         switch (((NMHDR FAR *) lParam)->code) 
  395.         {
  396.             case PSN_SETACTIVE:
  397.                 PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
  398.                 return(TRUE);
  399.             
  400.             case PSN_WIZNEXT: 
  401.                 if (gbIsHost)
  402.                     SetWindowLong(hDlg, DWL_MSGRESULT, IDD_HOSTSESSION);
  403.                 return(TRUE);
  404.  
  405.             case PSN_QUERYCANCEL:
  406.                 ReleaseSPData();
  407.                 DPlayRelease();
  408.                 return(TRUE);
  409.         }
  410.         break;
  411.  
  412.     case WM_INITDIALOG:
  413.         // setup title fonts
  414.         SendDlgItemMessage(hDlg, IDC_GAMESETUP_TITLE, WM_SETFONT, (WPARAM)ghTitleFont, MAKELPARAM(TRUE,0));
  415.         SendDlgItemMessage(hDlg, IDC_JOINSESSION, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  416.         SendDlgItemMessage(hDlg, IDC_HOSTSESSION, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  417.         // host by default
  418.         SendDlgItemMessage(hDlg, IDC_HOSTSESSION, BM_SETCHECK, 1, 0);
  419.         SendDlgItemMessage(hDlg, IDC_JOINSESSION, BM_SETCHECK, 0, 0);
  420.         gbIsHost = TRUE;
  421.         return(TRUE);
  422.  
  423.     case WM_COMMAND:
  424.         if (HIWORD(wParam) == BN_CLICKED)
  425.             switch (LOWORD(wParam))
  426.             {
  427.             case IDC_HOSTSESSION:
  428.                 if (SendDlgItemMessage(hDlg, IDC_HOSTSESSION, BM_GETCHECK, 1, 0) == 1)
  429.                 {
  430.                     gbIsHost = TRUE;
  431.                 }
  432.                 return(TRUE);
  433.             case IDC_JOINSESSION:
  434.                 if (SendDlgItemMessage(hDlg, IDC_JOINSESSION, BM_GETCHECK, 1, 0) == 1)
  435.                 {
  436.                     gbIsHost = FALSE;
  437.                 }
  438.                 return(TRUE);
  439.             }
  440.         break;
  441.     }
  442.     return(FALSE);
  443. }
  444.  
  445. /*
  446.  * EnumPlayer
  447.  *
  448.  * EnumeratePlayer callback. Inserts player information into the passed in tree view control.
  449.  */
  450. BOOL WINAPI EnumPlayer(DPID pidID, DWORD dwPlayerType, LPCDPNAME lpName,
  451.     DWORD dwFlags, LPVOID lpContext)
  452. {
  453.     HWND hWnd = (HWND) lpContext;
  454.     HTREEITEM hItem;
  455.  
  456. #ifdef UNICODE
  457.     hItem = AddItemToTree(hWnd, lpName->lpszShortName, 0, -1);
  458. #else
  459.     hItem = AddItemToTree(hWnd, lpName->lpszShortNameA, 0, -1);
  460. #endif
  461.  
  462.     return(TRUE);
  463. }
  464.  
  465. /*
  466.  * DlgProcJoinSession
  467.  *
  468.  * Dialog procedure for Join Session Dialog
  469.  */
  470. BOOL CALLBACK DlgProcJoinSession (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  471. {
  472.     static  NM_TREEVIEW nmtv;
  473.     static  HWND hWndCtl;
  474.     static  TCHAR tszPlayerName[MAX_PLAYERNAME+1];
  475.     static  HANDLE  dphEvent = NULL;
  476.     TV_ITEM tvItem;
  477.     TCHAR   tszSessionName[MAX_SESSIONNAME+1];
  478.     WCHAR   wszSPGuid[GUIDSTR_MAX+1];
  479.     BYTE    szSPGuid[GUIDSTR_MAX+1];
  480.     DWORD   dwPNameSize;
  481.     HRESULT hr;
  482.     HTREEITEM htiCur, htiNext;
  483.     LPGUID  lpGuid;
  484.  
  485.     switch (msg)
  486.     {
  487.     case WM_NOTIFY:
  488.         switch (((NMHDR FAR *) lParam)->code) 
  489.         {
  490.             case PSN_SETACTIVE:
  491.                 if (hWndCtl) TreeView_DeleteAllItems(hWndCtl);
  492.  
  493.                 // enum sessions and let dplay decide the timeout
  494.                 DPlayEnumSessions(0, EnumSession, (LPVOID) hWndCtl, (DWORD)NULL);
  495.  
  496.                 // enumerate players for all sessions
  497.                 ghtiSession = TreeView_GetFirstVisible(hWndCtl);
  498.         
  499.                 while (ghtiSession)
  500.                 {
  501.                     // delete previous players from display
  502.                     if ((htiNext = htiCur = TreeView_GetChild(hWndCtl, ghtiSession)) 
  503.                         != (HTREEITEM)0)
  504.                     {
  505.                         do
  506.                         {
  507.                             htiNext = TreeView_GetNextSibling(hWndCtl, htiCur);
  508.                             TreeView_DeleteItem(hWndCtl, htiCur);
  509.                             htiCur = htiNext;
  510.                         } while (htiNext);
  511.                     }
  512.  
  513.                     tvItem.hItem = ghtiSession;
  514.                     tvItem.pszText = tszSessionName;
  515.                     tvItem.cchTextMax = MAX_SESSIONNAME;
  516.                     TreeView_GetItem(hWndCtl, &tvItem);
  517.                     // enumerate players for selected session
  518.                     DPlayEnumPlayers((LPGUID)tvItem.lParam, EnumPlayer, (LPVOID) hWndCtl, DPENUMPLAYERS_SESSION);
  519.                     ghtiSession = TreeView_GetNextItem(hWndCtl, ghtiSession, TVGN_NEXTVISIBLE);
  520.                 }
  521.  
  522.                 // set Finish button highlite
  523.                 if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, tszPlayerName, MAX_PLAYERNAME) && 
  524.                     (htiCur = TreeView_GetSelection(hWndCtl)))
  525.                 {
  526.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  527.                 }
  528.                 else
  529.                 {
  530.                     PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  531.                 }
  532.  
  533.                 SetFocus(hWndCtl);
  534.                 return(TRUE);
  535.  
  536.             case PSN_WIZFINISH:
  537.                 // add user selections to registry
  538.                 if (ghDuelKey) 
  539.                 {
  540.                     StringFromGUID(&gSPGuid, wszSPGuid);
  541.                     WideToAnsi(szSPGuid, wszSPGuid, sizeof(wszSPGuid));
  542.                     RegSetA(TEXT("ServiceProvider"), szSPGuid, sizeof(szSPGuid));
  543.                     RegSet(TEXT("PlayerName"), (CONST BYTE *)tszPlayerName, 
  544.                             sizeof(tszPlayerName));
  545.                 }
  546.     
  547.                 // get the session guid
  548.                 if (nmtv.itemNew.lParam)
  549.                 {
  550.                     // user selected a session item, so just grab its lParam
  551.                     lpGuid = (LPGUID)nmtv.itemNew.lParam;
  552.                 }
  553.                 else
  554.                 {
  555.                     // user selected a player item, so grab its parent's (session) lParam
  556.                     htiCur = TreeView_GetParent(hWndCtl, nmtv.itemNew.hItem);
  557.                     if (!htiCur)
  558.                     {
  559.                         // fail finish
  560.                         ShowError(IDS_WIZARD_ERROR_GSG);
  561.                         SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  562.                         return (TRUE);
  563.                     }
  564.  
  565.                     tvItem.hItem = htiCur;
  566.                     tvItem.pszText = tszSessionName;
  567.                     tvItem.cchTextMax = MAX_SESSIONNAME;
  568.                     TreeView_GetItem(hWndCtl, &tvItem);                 
  569.                     lpGuid = (LPGUID)tvItem.lParam;
  570.                 }
  571.  
  572.                 // open session
  573.                 if ((hr = DPlayOpenSession(lpGuid)) != DP_OK)
  574.                 {
  575.                     // fail finish
  576.                     ShowError(IDS_DPLAY_ERROR_JS);
  577.                     SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  578.                     return (TRUE);
  579.                 }
  580.  
  581.                 // create player
  582.                 if ((hr = DPlayCreatePlayer(&gOurID, tszPlayerName, NULL, NULL, 0)) != DP_OK)
  583.                 {
  584.                     // fail finish
  585.                     ShowError(IDS_DPLAY_ERROR_CP);
  586.                     SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  587.                     return (TRUE);
  588.                 }
  589.  
  590.                 // everything went well, release allocated memory and finish
  591.                 ReleaseSessionData(hWndCtl);
  592.                 ReleaseSPData();                
  593.                 return(TRUE);
  594.  
  595.             case PSN_QUERYCANCEL:
  596.                 ReleaseSPData();
  597.                 ReleaseSessionData(hWndCtl);
  598.                 DPlayRelease();
  599.                 return(TRUE);
  600.  
  601.             case PSN_WIZBACK:
  602.                 ReleaseSessionData(hWndCtl);
  603.                 return(TRUE);
  604.  
  605.             case TVN_SELCHANGING:
  606.                 nmtv = *((NM_TREEVIEW *) lParam);
  607.  
  608.                 // set Finish button status 
  609.                 if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, tszPlayerName, MAX_PLAYERNAME) && 
  610.                     (htiCur = TreeView_GetSelection(hWndCtl)))
  611.                 {
  612.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  613.                 }
  614.                 else
  615.                 {
  616.                     PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  617.                 }
  618.                 return(FALSE);
  619.  
  620.             case NM_CLICK:
  621.                 return(FALSE);
  622.         }
  623.         break;
  624.     case WM_INITDIALOG:
  625.         // setup title fonts
  626.         SendDlgItemMessage(hDlg, IDC_JOIN_SESSION_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  627.         SendDlgItemMessage(hDlg, IDC_JOIN_PLAYER_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  628.  
  629.         // setup user's previous data
  630.         dwPNameSize = MAX_PLAYERNAME+1;
  631.         tszPlayerName[0]=0;
  632.         if (ghDuelKey && (RegGet(TEXT("PlayerName"),(LPBYTE)tszPlayerName,&dwPNameSize) == ERROR_SUCCESS))  
  633.             SetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, tszPlayerName);
  634.  
  635.         hWndCtl = GetDlgItem(hDlg, IDC_JOIN_SESSION);
  636.         if (hWndCtl == NULL) return(TRUE);
  637.         InitTreeViewImageLists(hWndCtl);
  638.         return(TRUE);
  639.  
  640.     case WM_COMMAND:
  641.  
  642.         switch (LOWORD(wParam))
  643.         {
  644.         case IDC_JOIN_PLAYERNAME:
  645.             if (HIWORD(wParam) == EN_CHANGE)
  646.             {
  647.                 // set Finish button status 
  648.                 if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, tszPlayerName, MAX_PLAYERNAME) && 
  649.                     (htiCur = TreeView_GetSelection(hWndCtl)))
  650.                 {
  651.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  652.                 }
  653.                 else
  654.                 {
  655.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  656.                 }
  657.             }
  658.             break;
  659.         }
  660.         break;
  661.     }
  662.     return (FALSE);
  663. }
  664.  
  665. /*
  666.  * DlgProcHostSession
  667.  *
  668.  * Dialog proc for Host Session Dialog
  669.  */
  670. BOOL CALLBACK DlgProcHostSession(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  671. {
  672.     static  TCHAR tszSessionName[MAX_SESSIONNAME+1], tszPlayerName[MAX_PLAYERNAME+1];
  673.     HRESULT hr;
  674.     WCHAR   wszSPGuid[GUIDSTR_MAX+1];
  675.     BYTE    szSPGuid[GUIDSTR_MAX+1];
  676.     DWORD   dwPNameSize, dwSNameSize;
  677.  
  678.     switch (msg) {
  679.     case WM_NOTIFY:
  680.         switch (((NMHDR FAR *) lParam)->code) 
  681.         {
  682.             case PSN_SETACTIVE:
  683.                 if (GetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, tszSessionName, MAX_SESSIONNAME) && 
  684.                     GetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, tszPlayerName, MAX_PLAYERNAME))
  685.                 {
  686.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  687.                 }
  688.                 else
  689.                 {
  690.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  691.                 }
  692.                 return(TRUE);
  693.     
  694.             case PSN_WIZFINISH:
  695.                 // add user selections to registry
  696.                 if (ghDuelKey) 
  697.                 {
  698.                     StringFromGUID(&gSPGuid, wszSPGuid);
  699.                     WideToAnsi(szSPGuid, wszSPGuid, sizeof(wszSPGuid));
  700.                     RegSetA(TEXT("ServiceProvider"), szSPGuid, sizeof(szSPGuid));
  701.                     RegSet(TEXT("PlayerName"), (CONST BYTE *)tszPlayerName, sizeof(tszPlayerName));
  702.                     RegSet(TEXT("SessionName"), (CONST BYTE *)tszSessionName, sizeof(tszSessionName));
  703.                 }
  704.  
  705.                 // create session
  706.                 if ((hr = DPlayCreateSession(tszSessionName)) != DP_OK)
  707.                 {
  708.                     // fail finish
  709.                     ShowError(IDS_DPLAY_ERROR_CS);
  710.                     SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  711.                     return (TRUE);
  712.                 }
  713.  
  714.                 // create player
  715.                 if ((hr = DPlayCreatePlayer(&gOurID, tszPlayerName, NULL, NULL, 0)) != DP_OK)
  716.                 {
  717.                     ShowError(IDS_DPLAY_ERROR_CP);
  718.                     SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  719.                     return (TRUE);
  720.                 }
  721.  
  722.                 // everything went well, release allocated memory and finish
  723.                 ReleaseSPData();
  724.                 return(TRUE);
  725.             
  726.             case PSN_WIZBACK:
  727.                 SetWindowLong(hDlg, DWL_MSGRESULT, IDD_GAMESETUP);
  728.                 return(TRUE);
  729.  
  730.             case PSN_QUERYCANCEL:
  731.                 // release allocated memory
  732.                 ReleaseSPData();
  733.                 // release dplay
  734.                 DPlayRelease();
  735.                 return(TRUE);
  736.         }
  737.         break;
  738.     case WM_INITDIALOG:
  739.         // setup title font
  740.         SendDlgItemMessage(hDlg, IDC_HOST_TITLE, WM_SETFONT, (WPARAM)ghTitleFont, MAKELPARAM(TRUE,0));
  741.         SendDlgItemMessage(hDlg, IDC_HOST_SESSION_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  742.         SendDlgItemMessage(hDlg, IDC_HOST_PLAYER_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  743.  
  744.         dwPNameSize = MAX_PLAYERNAME+1;
  745.         dwSNameSize = MAX_SESSIONNAME+1;
  746.         tszPlayerName[0]=0;
  747.         tszSessionName[0]=0;
  748.         if (ghDuelKey)
  749.         {
  750.             if (RegGet(TEXT("PlayerName"), (LPBYTE)tszPlayerName, &dwPNameSize) == ERROR_SUCCESS)   
  751.                 SetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, tszPlayerName);
  752.             if (RegGet(TEXT("SessionName"), (LPBYTE)tszSessionName, &dwSNameSize) == ERROR_SUCCESS) 
  753.                 SetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, tszSessionName);
  754.         }
  755.         
  756.         return(TRUE);
  757.  
  758.     case WM_COMMAND:
  759.         switch (LOWORD(wParam))
  760.         {
  761.         case IDC_HOST_SESSIONNAME:
  762.             if (HIWORD(wParam) == EN_CHANGE)
  763.             {
  764.                 if (GetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, tszSessionName, MAX_SESSIONNAME) && 
  765.                     GetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, tszPlayerName, MAX_PLAYERNAME))
  766.                 {
  767.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  768.                 }
  769.                 else
  770.                 {
  771.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  772.                 }
  773.  
  774.                 return TRUE;
  775.             }
  776.             break;
  777.  
  778.         case IDC_HOST_PLAYERNAME:
  779.             if (HIWORD(wParam) == EN_CHANGE)
  780.             {
  781.                 if (GetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, tszSessionName, MAX_SESSIONNAME) && 
  782.                     GetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, tszPlayerName, MAX_PLAYERNAME))
  783.                 {
  784.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  785.                 }
  786.                 else
  787.                 {
  788.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  789.                 }
  790.             }
  791.             break;
  792.         }
  793.         break;
  794.     }
  795.  
  796.     return(FALSE);
  797. }
  798.  
  799. /*
  800.  * InitTreeViewImageLists - creates an image list, adds three bitmaps to 
  801.  *     it, and associates the image list with a tree-view control. 
  802.  * Returns TRUE if successful or FALSE otherwise. 
  803.  * hwndTV - handle of the tree-view control 
  804.  *
  805.  * Global variables and constants 
  806.  *     gnSession, and gnPlayer - integer variables for 
  807.  *         indexes of the images 
  808.  *     CX_BITMAP and CY_BITMAP - width and height of an icon 
  809.  *     NUM_BITMAPS - number of bitmaps to add to the image list 
  810.  */
  811. BOOL InitTreeViewImageLists(HWND hwndTV) 
  812.     HIMAGELIST himl;  // handle of image list 
  813.     HBITMAP hbmp;     // handle of bitmap 
  814.  
  815.     // Create the image list. 
  816.     if ((himl = ImageList_Create(CX_BITMAP, CY_BITMAP, 
  817.             FALSE, NUM_BITMAPS, 0)) == NULL) 
  818.         return FALSE; 
  819.  
  820.     // Add the session and player bitmaps. 
  821.     hbmp = LoadBitmap(ghinst, MAKEINTRESOURCE(IDB_CLOSED_SESSION)); 
  822.     gnSession = ImageList_Add(himl, hbmp, (HBITMAP) NULL); 
  823.     DeleteObject(hbmp); 
  824.  
  825.     hbmp = LoadBitmap(ghinst, MAKEINTRESOURCE(IDB_PLAYER)); 
  826.     gnPlayer = ImageList_Add(himl, hbmp, (HBITMAP) NULL); 
  827.     DeleteObject(hbmp); 
  828.  
  829.     // Fail if not all of the images were added. 
  830.     if (ImageList_GetImageCount(himl) < 2) 
  831.         return FALSE; 
  832.  
  833.     // Associate the image list with the tree-view control. 
  834.     TreeView_SetImageList(hwndTV, himl, TVSIL_NORMAL); 
  835.  
  836.     return TRUE; 
  837.    
  838.  
  839. /*
  840.  * AddItemToTree - adds items to a tree-view control. 
  841.  * Returns the handle of the newly added item. 
  842.  * hwndTV - handle of the tree-view control 
  843.  * lpszItem - text of the item to add 
  844.  * nLevel - level at which to add the item 
  845.  */
  846. HTREEITEM AddItemToTree(HWND hwndTV, LPTSTR lptszItem, DWORD dwData, int nLevel) 
  847.     TV_ITEM tvi; 
  848.     TV_INSERTSTRUCT tvins; 
  849.     static HTREEITEM hPrev = (HTREEITEM) TVI_FIRST; 
  850.     static HTREEITEM hPrevRootItem = NULL; 
  851.     static HTREEITEM hPrevLev2Item = NULL; 
  852.  
  853.     tvi.mask = TVIF_TEXT | TVIF_IMAGE 
  854.         | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  855.     
  856.     // Set the state
  857.     if (nLevel == 1) 
  858.     {
  859.         tvi.mask |= TVIF_STATE; 
  860.         tvi.state = TVIS_SELECTED;
  861.     }
  862.  
  863.     // Set the text of the item. 
  864.     tvi.pszText = lptszItem; 
  865.  
  866.    // Set the image
  867.     if (nLevel == 1)
  868.     {
  869.         tvi.iImage = gnSession; 
  870.         tvi.iSelectedImage = gnSession; 
  871.     }
  872.     else
  873.     {
  874.         tvi.iImage = gnPlayer; 
  875.         tvi.iSelectedImage = gnPlayer; 
  876.     }
  877.  
  878.  
  879.     // Save the heading level in the item's application-defined 
  880.     // data area. 
  881.     tvi.lParam = (LPARAM) dwData; 
  882.  
  883.     tvins.item = tvi; 
  884.     tvins.hInsertAfter = hPrev; 
  885.  
  886.     // Set the parent item based on the specified level. 
  887.     if (nLevel == -1)
  888.         tvins.hParent = ghtiSession;
  889.     else if (nLevel == 1) 
  890.         tvins.hParent = TVI_ROOT; 
  891.     else if (nLevel == 2) 
  892.         tvins.hParent = hPrevRootItem; 
  893.     else
  894.         tvins.hParent = hPrevLev2Item; 
  895.  
  896.     // Add the item to the tree-view control. 
  897.     hPrev = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, 
  898.          (LPARAM) (LPTV_INSERTSTRUCT) &tvins); 
  899.  
  900.     // Save the handle of the item. 
  901.     if (nLevel == 1) 
  902.         hPrevRootItem = hPrev; 
  903.     else if (nLevel == 2) 
  904.         hPrevLev2Item = hPrev; 
  905.  
  906.     return hPrev; 
  907.  
  908. /*
  909.  * ReleaseSessionData
  910.  *
  911.  * Releases the memory allocated for session guids
  912.  */
  913. void ReleaseSessionData(HWND hWndCtl)
  914. {
  915.     HTREEITEM htiSession;
  916.     TV_ITEM tvItem;
  917.     TCHAR tszSessionName[MAX_SESSIONNAME+1];
  918.  
  919.  
  920.     htiSession = TreeView_GetRoot(hWndCtl);
  921.     while (htiSession)
  922.     {
  923.         tvItem.hItem = htiSession;
  924.         tvItem.pszText = tszSessionName;
  925.         tvItem.cchTextMax = MAX_SESSIONNAME;
  926.         TreeView_GetItem(hWndCtl, &tvItem);
  927.         if (tvItem.lParam) free((LPVOID)tvItem.lParam);
  928.         htiSession = TreeView_GetNextSibling(hWndCtl, htiSession);
  929.     }
  930. }
  931.  
  932. /*
  933.  * ReleaseSPData
  934.  *
  935.  * Releases the memory allocated for service provider guids
  936.  * depends on global variable ghWndSPControl
  937.  */
  938. void ReleaseSPData(void)
  939. {
  940.     LPGUID lpGuid;
  941.     int count,index;
  942.  
  943.     if (ghWndSPCtl)
  944.     {
  945.         count = SendMessage(ghWndSPCtl, LB_GETCOUNT, 0, 0);
  946.         for (index = 0; index < count; index++)
  947.         {
  948.             lpGuid = (LPGUID) SendMessage(ghWndSPCtl, LB_GETITEMDATA, index, 0);
  949.             if (lpGuid) free(lpGuid);
  950.         }
  951.     }
  952. }
  953.